package es.esa.integral;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.text.DecimalFormat;

/**
 * Created by esalazar on 4/25/14.
 */
public class JSONServiceClient {
    private static JSONServiceClient instance = null;
    private static final DecimalFormat df2 = new DecimalFormat("#.00");
    private static final String EMT_URL="http://integral.esac.esa.int/isocweb/exposureMap.html?action=query&first=%s&second=%s&exposureQuery=T&coordinates=equatorial&map=ALL_MAPS&format=json";
    private static final String PQT_URL="http://integral.esac.esa.int/isocweb/queryProposals.html?action=query&sourceName1=&first1=%s&second1=%s&exposureQuery=T&coordinates=equatorial&map=ALL_MAPS&format=json";
    private static final String TVP_URL="http://integral.esa.int/isocweb/tvp.html?startDate=01-01-2015&duration=1800&dither=R&action=predict&endDate=31-12-2015&coordinates=equatorial&ra=%s&dec=%s&format=json";

    private JSONServiceClient() {};

    public static JSONServiceClient getInstance() {
        if (instance == null) {
            instance = new JSONServiceClient();
        }
        return instance;
    }


    private String getURL(String url, String ra, String dec) {
         return String.format(url, ra, dec);

    }


    public  Double getVisibility(double ra, double dec) throws IOException, JSONException {
        String url = getURL(TVP_URL, df2.format(ra), df2.format(dec));
        ConnectionToService conn = new ConnectionToService(url);
        JSONObject tvpJSON =  new JSONObject(conn.sb.toString());
        conn.close();
        Double duration = tvpJSON.getDouble("TOTAL_DURATION");
        Double durationInKs = duration/1000;
        return  durationInKs;

    }

    public ExposureInstruments getExposure(double ra, double dec) throws IOException, JSONException  {
        String url = getURL(EMT_URL, df2.format(ra), df2.format(dec));
        ConnectionToService conn = new ConnectionToService(url);
        JSONObject objJSON =  new JSONObject(conn.sb.toString());
        conn.close();
        String ibis = objJSON.getString("EXPOSURE IBIS").replaceAll(",", "");
        String spi = objJSON.getString("EXPOSURE SPI").replaceAll(",", "");
        return new ExposureInstruments(Double.valueOf(ibis), Double.valueOf(spi));
    }

    public ExposureInstruments getExpectedExposure(double ra, double dec, String propId) throws IOException, JSONException  {
        if (propId.charAt(2) == '4') return new ExposureInstruments(-1d,-1d);
        String url = getURL(PQT_URL, df2.format(ra), df2.format(dec));
        ConnectionToService conn = new ConnectionToService(url);
        JSONObject objJSON =  new JSONObject(conn.sb.toString());
        JSONArray arrayJSON = objJSON.getJSONArray("proposals");
        JSONObject proposalJSON = null;

        for (int i = 0; i <arrayJSON.length(); i++) {
            proposalJSON = arrayJSON.getJSONObject(i);
            String proposalIdJSON = proposalJSON.getString("proposal");
            if (propId.substring(0,2).equals(proposalIdJSON.substring(0,2)) && propId.substring(3).equals(proposalIdJSON.substring(3))) {
                conn.close();
                Double exposureKS = Double.valueOf(proposalJSON.getString("exposure"))/1000;
                return new ExposureInstruments(exposureKS,exposureKS);
            }

        }

        conn.close();

        return new ExposureInstruments(0d,0d);


    }
    public static HttpURLConnection initConnection(URL url)
            throws IOException, ProtocolException {
        HttpURLConnection hc;
        hc = (HttpURLConnection) url.openConnection();
        hc.setRequestMethod("GET");
        hc.setDoInput(true);
        hc.setDoOutput(true);
        hc.setUseCaches(false);

        hc.setRequestProperty("content-type",
                "application/json; charset=utf-8");
        hc.connect();
        return hc;
    }

    public static class ExposureInstruments {
        public final Double ibis;
        public final Double spi;
        public ExposureInstruments(Double ibis, Double spi) {
            this.ibis =  ibis;
            this.spi = spi;
        }

        public String getIbisFormatted() {
            return df2.format(Double.valueOf(ibis));
        }
        public String getSpiFormatted() {
            return df2.format(Double.valueOf(spi));
        }
    }

    private static class ConnectionToService {
        private final HttpURLConnection hc;
        private final InputStreamReader in;
        private final BufferedReader buff;
        private final StringBuilder sb;

        public ConnectionToService(String urlString) throws ProtocolException, IOException {
            URL url = new URL(urlString);
            hc = initConnection(url);
            in = new InputStreamReader((InputStream) hc
                    .getContent());
            buff = new BufferedReader(new InputStreamReader((InputStream) hc
                    .getContent(), "iso-8859-1"), 8);
            sb = new StringBuilder();
            String line = null;
            while ( (line = buff.readLine())!= null) {
                sb.append(line);
            }
        }

        public void close() throws IOException{
            buff.close();
            in.close();
            hc.disconnect();
        }




    }

}
